#include "stdafx.h"
#include "HTTPResponser.h"
#include "HTTPCloseEnum.h"
#include "ServerResponseCode.h"

#define MAX_CONTENT_LENGTH 4096


const char* G_HTTP_Bad_Request = "400 Bad Request - C++ HTTP Server";

HTTPResponser::HTTPResponser(AbstractHTTPServer * server, IOCPNetwork* iocp)
	:server(server),
	iocp(iocp),
	connId(NULL)
{
}


HTTPResponser::~HTTPResponser()
{
}

void * HTTPResponser::getConnectionId()
{
	return connId;
}

__int64 HTTPResponser::getTotalSentBytes()
{
	return 0;
}

__int64 HTTPResponser::getTotalRecvBytes()
{
	return 0;
}

int HTTPResponser::getServerCode()
{
	return 0;
}

std::string HTTPResponser::getHeader()
{
	return std::string();
}

int HTTPResponser::run(void * connId, void * clientSock, AbstractIRequest * request)
{
	if (this->socketBuff)
	{
		return RE_INTERNAL_ERROR;
	}

	// 属性赋值

	this->connId = connId;

	this->clientSocket = clientSock;

	this->request = request;

	this->httpContent = new HTTPContent();

	this->socketBuff = new char[MAX_CONTENT_LENGTH];

	this->socketBuffLength = 0;


	// 处理请求信息

	int code = SERVER_OK;

	do
	{
		
		// 非法请求 或请求头过大

		if (this->request->isValid())
		{
			code = SERVER_BADREQUEST;

			this->httpContent->open(G_HTTP_Bad_Request, strlen(G_HTTP_Bad_Request), S_OPEN_HTML);

			break;
		}

		// 静态文件只支持 GET 和 HEAD 方法

		// 打开文件


	} while (0);

	/*生成响应并发送第一个数据包*/

	assert(this->httpContent->isOpen());

	// 生成响应头
	this->makeResponserHeader(code);


	if (this->request->method() == METHOD_HEAD)
	{
		this->httpContent->close();

		delete this->httpContent;

		this->httpContent = NULL;
	}

	// 发送第一个响应包

	// 读取响应头

	if (this->socketBuffLength < MAX_CONTENT_LENGTH)
	{
		this->socketBuffLength += this->reponseHeader.read(this->socketBuff + this->socketBuffLength, MAX_CONTENT_LENGTH - this->socketBuffLength);
	}

	// 读取内容
	if (this->httpContent && this->httpContent->isOpen() && (this->socketBuffLength < MAX_CONTENT_LENGTH))
	{
		this->socketBuffLength += this->httpContent->read(this->socketBuff + this->socketBuffLength, MAX_CONTENT_LENGTH - this->socketBuffLength);
	}

	// 发送内容

	int receCode = this->iocp->sendContent(this->clientSocket, reinterpret_cast<byte*>(this->socketBuff), this->socketBuffLength, this->server->recvTimeout(), IOCPCallbackSend, this);

	if (IOCP_PENDING != receCode)
	{
		this->reset();

		return (IOCP_SESSIONTIMEO ? RE_SESSION_TIMEO : RE_CLIENTCLOSED);
	}

	return RE_SUCCESS;
}

bool HTTPResponser::stop(int ec)
{
	return false;
}

bool HTTPResponser::reset()
{
	if (this->httpContent)
	{
		if (this->httpContent->isOpen())
		{
			this->httpContent->close();
		}

		delete this->httpContent;

		this->httpContent = NULL;
	}

	if (this->socketBuff)
	{
		delete[] this->socketBuff;

		this->socketBuff = NULL;
	}

	this->socketBuffLength = 0;

	this->byteSend = 0;

	this->request = NULL;

	this->clientSocket = IOCP_NULLKEY;

	this->serverCode = SERVER_UNKNOWN;

	this->connId = NULL;

	this->reponseHeader.reset();


	return false;
}

void HTTPResponser::IOCPCallbackSend(void * s, int flags, bool result, int transfered, byte * buf, size_t len, void * param)
{
	HTTPResponser * responser = reinterpret_cast<HTTPResponser *>(param);

	if (flags & IOCP_SEND)
	{
		responser->onSend(transfered, flags);
	}
	else
	{
		assert(0);
	}
}

void HTTPResponser::onSend(size_t bytesTransfered, int flags)
{
	if (bytesTransfered == 0)
	{
		this->close((flags & IOCP_WRITETIMEO) ? RE_SEND_TIMEO : RE_CLIENTCLOSED);
	}
	else
	{
		this->byteSend += bytesTransfered;

		this->socketBuffLength -= bytesTransfered;

		// 缓冲区内是否还有数据，有则移到头部

		if (this->socketBuffLength > 0)
		{
			memmove_s(this->socketBuff, this->socketBuffLength, this->socketBuff+ bytesTransfered, this->socketBuffLength);
		}

		// 继续读取响应头
		if (this->socketBuffLength < MAX_CONTENT_LENGTH)
		{
			this->socketBuffLength += this->reponseHeader.read(this->socketBuff + this->socketBuffLength, MAX_CONTENT_LENGTH - this->socketBuffLength);
		}

		// 读取响应数据内容
		if (this->httpContent->isOpen() && this->socketBuffLength < MAX_CONTENT_LENGTH)
		{
			this->socketBuffLength += this->httpContent->read(this->socketBuff + this->socketBuffLength, MAX_CONTENT_LENGTH - this->socketBuffLength);
		}

		if (this->socketBuffLength == 0)
		{
			this->close(RE_SENDCOMPLETE);
		}
		else
		{
			// 继续发送
			int netIoRet = this->iocp->sendContent(this->clientSocket, reinterpret_cast<byte *>(this->socketBuff), this->socketBuffLength, this->server->sendTimeout(), IOCPCallbackSend, this);
			
			if (netIoRet != IOCP_PENDING) 
			{
				this->close(IOCP_SESSIONTIMEO == netIoRet ? RE_SEND_TIMEO: RE_CLIENTCLOSED);
			}
		}

	}
}

void HTTPResponser::close(int code)
{
	this->server->onResponder(this, code);
}

bool HTTPResponser::makeResponserHeader(unsigned int code)
{
	this->serverCode = code;

	this->reponseHeader.setResponseCode(code);

	this->reponseHeader.addDefaultHeaderField();

	if (code = SERVER_BADMETHOD) {
		this->reponseHeader.addHeader("Allow", "GET, HEAD, POST, PUT");
	}
	
	if (this->httpContent && this->httpContent->isOpen())
	{
		this->reponseHeader.addHeader("Last-Modified", this->httpContent->lastModifield());

		// ETag
		this->reponseHeader.addHeader("ETag", this->httpContent->getETag());

		// Content-Type
		this->reponseHeader.addHeader("Content-Type", this->httpContent->getContentType());

		// Content-Length
		this->reponseHeader.addHeader("Content-Length", std::to_string(this->httpContent->getContentLength()));

		// 断点续传// Content-Range: bytes %d-%d/%d\r\n"
		if (this->serverCode == SERVER_PARTIAL)
		{
			this->reponseHeader.addHeader("Content-Range", this->httpContent->getContentRange());
		}

		// "Accept-Ranges: bytes" 支持断点续传(只有静态文件支持断点续传). 后续添加

	}
	else
	{
		// Content-Length 
		this->reponseHeader.addHeader("Content-Length", "0");
	}

	if (this->request->keepAlive())
	{
		this->reponseHeader.addHeader("Connection", "keep-alive");
	}
	else
	{
		this->reponseHeader.addHeader("Connection", "close");
	}

	// 格式化相应头准备输出
	this->reponseHeader.formate();

	return true;
}
